home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 002 / emacssrc.arc / BIND.C < prev    next >
C/C++ Source or Header  |  1987-02-03  |  16KB  |  677 lines

  1. /*    This file is for functions having to do with key bindings,
  2.     descriptions, help commands and startup file.
  3.  
  4.     written 11-feb-86 by Daniel Lawrence
  5.                                 */
  6.  
  7. #include    <stdio.h>
  8. #include    "estruct.h"
  9. #include    "edef.h"
  10. #include    "epath.h"
  11.  
  12. #if    MEGAMAX & ST520
  13. overlay    "bind"
  14. #endif
  15.  
  16. extern int meta(), cex(), unarg(), ctrlg(); /* dummy prefix binding functions */
  17.  
  18. deskey(f, n)    /* describe the command for a certain key */
  19.  
  20. {
  21.     register int c;        /* command character to describe */
  22.     register char *ptr;    /* string pointer to scan output strings */
  23.     register KEYTAB *ktp;    /* pointer into the command table */
  24.     register int found;    /* matched command flag */
  25.     register NBIND *nptr;    /* pointer into the name binding table */
  26.     char outseq[80];    /* output buffer for command sequence */
  27.  
  28.     /* prompt the user to type us a key to describe */
  29.     mlwrite(": describe-key ");
  30.  
  31.     /* get the command sequence to describe */
  32.     c = getckey(FALSE);            /* get a command sequence */
  33.  
  34.     /* change it to something we can print as well */
  35.     cmdstr(c, &outseq[0]);
  36.  
  37.     /* and dump it out */
  38.     ptr = &outseq[0];
  39.     while (*ptr)
  40.         TTputc(*ptr++);
  41.     TTputc(' ');        /* space it out */
  42.  
  43.     /* find the right ->function */
  44.     ktp = &keytab[0];
  45.     found = FALSE;
  46.     while (ktp->k_fp != NULL) {
  47.         if (ktp->k_code == c) {
  48.             found = TRUE;
  49.             break;
  50.         }
  51.         ++ktp;
  52.     }
  53.  
  54.     if (!found)
  55.         strcpy(outseq,"Not Bound");
  56.     else {
  57.         /* match it against the name binding table */
  58.         nptr = &names[0];
  59.         strcpy(outseq,"[Bad binding]");
  60.         while (nptr->n_func != NULL) {
  61.             if (nptr->n_func == ktp->k_fp) {
  62.                 strcpy(outseq, nptr->n_name);
  63.                 break;
  64.             }
  65.             ++nptr;
  66.         }
  67.     }
  68.  
  69.     /* output the command sequence */
  70.     ptr = &outseq[0];
  71.     while (*ptr)
  72.         TTputc(*ptr++);
  73. }
  74.  
  75. cmdstr(c, seq)    /* change a key command to a string we can print out */
  76.  
  77. int c;        /* sequence to translate */
  78. char *seq;    /* destination string for sequence */
  79.  
  80. {
  81.     char *ptr;    /* pointer into current position in sequence */
  82.  
  83.     ptr = seq;
  84.  
  85.     /* apply meta sequence if needed */
  86.     if (c & META) {
  87.         *ptr++ = 'M';
  88.         *ptr++ = '-';
  89.     }
  90.  
  91.     /* apply ^X sequence if needed */
  92.     if (c & CTLX) {
  93.         *ptr++ = '^';
  94.         *ptr++ = 'X';
  95.     }
  96.  
  97.     /* apply SPEC sequence if needed */
  98.     if (c & SPEC) {
  99.         *ptr++ = 'F';
  100.         *ptr++ = 'N';
  101.     }
  102.  
  103.     /* apply control sequence if needed */
  104.     if (c & CTRL) {
  105.         *ptr++ = '^';
  106.     }
  107.  
  108.     c = c & 255;    /* strip the prefixes */
  109.  
  110.     /* and output the final sequence */
  111.  
  112.     *ptr++ = c;
  113.     *ptr = 0;    /* terminate the string */
  114. }
  115.  
  116. help(f, n)    /* give me some help!!!!
  117.            bring up a fake buffer and read the help file
  118.            into it with view mode            */
  119. {
  120.     register WINDOW *wp;    /* scaning pointer to windows */
  121.     register BUFFER *bp;    /* buffer pointer to help */
  122.     char *fname;        /* ptr to file returned by flook() */
  123.  
  124.     /* first check if we are already here */
  125.     bp = bfind("emacs.hlp", FALSE, BFINVS);
  126.  
  127.     if (bp == NULL) {
  128.         fname = flook(pathname[1], FALSE);
  129.         if (fname == NULL) {
  130.             mlwrite("[Help file is not online]");
  131.             return(FALSE);
  132.         }
  133.     }
  134.  
  135.     /* split the current window to make room for the help stuff */
  136.     if (splitwind(FALSE, 1) == FALSE)
  137.             return(FALSE);
  138.  
  139.     if (bp == NULL) {
  140.         /* and read the stuff in */
  141.         if (getfile(fname, FALSE) == FALSE)
  142.             return(FALSE);
  143.     } else
  144.         swbuffer(bp);
  145.  
  146.     /* make this window in VIEW mode, update all mode lines */
  147.     curwp->w_bufp->b_mode |= MDVIEW;
  148.     curwp->w_bufp->b_flag |= BFINVS;
  149.     wp = wheadp;
  150.     while (wp != NULL) {
  151.         wp->w_flag |= WFMODE;
  152.         wp = wp->w_wndp;
  153.     }
  154.     return(TRUE);
  155. }
  156.  
  157. int (*fncmatch(fname))() /* match fname to a function in the names table
  158.                 and return any match or NULL if none        */
  159.  
  160. char *fname;    /* name to attempt to match */
  161.  
  162. {
  163.     register NBIND *ffp;    /* pointer to entry in name binding table */
  164.  
  165.     /* scan through the table, returning any match */
  166.     ffp = &names[0];
  167.     while (ffp->n_func != NULL) {
  168.         if (strcmp(fname, ffp->n_name) == 0)
  169.             return(ffp->n_func);
  170.         ++ffp;
  171.     }
  172.     return(NULL);
  173. }
  174.  
  175. /* bindtokey:    add a new key to the key binding table        */
  176.  
  177. bindtokey(f, n)
  178.  
  179. int f, n;    /* command arguments [IGNORED] */
  180.  
  181. {
  182.     register int c;        /* command key to bind */
  183.     register (*kfunc)();    /* ptr to the requexted function to bind to */
  184.     register char *ptr;    /* ptr to dump out input key string */
  185.     register KEYTAB *ktp;    /* pointer into the command table */
  186.     register int found;    /* matched command flag */
  187.     char outseq[80];    /* output buffer for keystroke sequence */
  188.     int (*getname())();
  189.  
  190.     /* prompt the user to type in a key to bind */
  191.     mlwrite(": bind-to-key ");
  192.  
  193.     /* get the function name to bind it to */
  194.     kfunc = getname();
  195.     if (kfunc == NULL) {
  196.         mlwrite("[No such function]");
  197.         return(FALSE);
  198.     }
  199.     TTputc(' ');        /* space it out */
  200.     TTflush();
  201.  
  202.     /* get the command sequence to bind */
  203.     c = getckey((kfunc == meta) || (kfunc == cex) ||
  204.                 (kfunc == unarg) || (kfunc == ctrlg));
  205.  
  206.     /* change it to something we can print as well */
  207.     cmdstr(c, &outseq[0]);
  208.  
  209.     /* and dump it out */
  210.     ptr = &outseq[0];
  211.     while (*ptr)
  212.         TTputc(*ptr++);
  213.  
  214.     /* if the function is a prefix key */
  215.     if (kfunc == meta || kfunc == cex ||
  216.         kfunc == unarg || kfunc == ctrlg) {
  217.  
  218.         /* search for an existing binding for the prefix key */
  219.         ktp = &keytab[0];
  220.         found = FALSE;
  221.         while (ktp->k_fp != NULL) {
  222.             if (ktp->k_fp == kfunc)
  223.                 unbindchar(ktp->k_code);
  224.             ++ktp;
  225.         }
  226.  
  227.         /* reset the appropriate global prefix variable */
  228.         if (kfunc == meta)
  229.             metac = c;
  230.         if (kfunc == cex)
  231.             ctlxc = c;
  232.         if (kfunc == unarg)
  233.             reptc = c;
  234.         if (kfunc == ctrlg)
  235.             abortc = c;
  236.     }
  237.  
  238.     /* search the table to see if it exists */
  239.     ktp = &keytab[0];
  240.     found = FALSE;
  241.     while (ktp->k_fp != NULL) {
  242.         if (ktp->k_code == c) {
  243.             found = TRUE;
  244.             break;
  245.         }
  246.         ++ktp;
  247.     }
  248.  
  249.     if (found) {    /* it exists, just change it then */
  250.         ktp->k_fp = kfunc;
  251.     } else {    /* otherwise we need to add it to the end */
  252.         /* if we run out of binding room, bitch */
  253.         if (ktp >= &keytab[NBINDS]) {
  254.             mlwrite("Binding table FULL!");
  255.             return(FALSE);
  256.         }
  257.  
  258.         ktp->k_code = c;    /* add keycode */
  259.         ktp->k_fp = kfunc;    /* and the function pointer */
  260.         ++ktp;            /* and make sure the next is null */
  261.         ktp->k_code = 0;
  262.         ktp->k_fp = NULL;
  263.     }
  264.     return(TRUE);
  265. }
  266.  
  267. /* unbindkey:    delete a key from the key binding table    */
  268.  
  269. unbindkey(f, n)
  270.  
  271. int f, n;    /* command arguments [IGNORED] */
  272.  
  273. {
  274.     register int c;        /* command key to unbind */
  275.     register char *ptr;    /* ptr to dump out input key string */
  276.     char outseq[80];    /* output buffer for keystroke sequence */
  277.  
  278.     /* prompt the user to type in a key to unbind */
  279.     mlwrite(": unbind-key ");
  280.  
  281.     /* get the command sequence to unbind */
  282.     c = getckey(FALSE);        /* get a command sequence */
  283.  
  284.     /* change it to something we can print as well */
  285.     cmdstr(c, &outseq[0]);
  286.  
  287.     /* and dump it out */
  288.     ptr = &outseq[0];
  289.     while (*ptr)
  290.         TTputc(*ptr++);
  291.  
  292.     /* if it isn't bound, bitch */
  293.     if (unbindchar(c) == FALSE) {
  294.         mlwrite("[Key not bound]");
  295.         return(FALSE);
  296.     }
  297.     return(TRUE);
  298. }
  299.  
  300. unbindchar(c)
  301.  
  302. int c;        /* command key to unbind */
  303.  
  304. {
  305.     register KEYTAB *ktp;    /* pointer into the command table */
  306.     register KEYTAB *sktp;    /* saved pointer into the command table */
  307.     register int found;    /* matched command flag */
  308.  
  309.     /* search the table to see if the key exists */
  310.     ktp = &keytab[0];
  311.     found = FALSE;
  312.     while (ktp->k_fp != NULL) {
  313.         if (ktp->k_code == c) {
  314.             found = TRUE;
  315.             break;
  316.         }
  317.         ++ktp;
  318.     }
  319.  
  320.     /* if it isn't bound, bitch */
  321.     if (!found)
  322.         return(FALSE);
  323.  
  324.     /* save the pointer and scan to the end of the table */
  325.     sktp = ktp;
  326.     while (ktp->k_fp != NULL)
  327.         ++ktp;
  328.     --ktp;        /* backup to the last legit entry */
  329.  
  330.     /* copy the last entry to the current one */
  331.     sktp->k_code = ktp->k_code;
  332.     sktp->k_fp   = ktp->k_fp;
  333.  
  334.     /* null out the last one */
  335.     ktp->k_code = 0;
  336.     ktp->k_fp = NULL;
  337.     return(TRUE);
  338. }
  339.  
  340. desbind(f, n)    /* describe bindings
  341.            bring up a fake buffer and list the key bindings
  342.            into it with view mode            */
  343.  
  344. #if    APROP
  345. {
  346.     buildlist(TRUE, "");
  347. }
  348.  
  349. apro(f, n)    /* Apropos (List functions that match a substring) */
  350.  
  351. {
  352.     char mstring[NSTRING];    /* string to match cmd names to */
  353.     int status;        /* status return */
  354.  
  355.     status = mlreply("Apropos string: ", mstring, NSTRING - 1);
  356.     if (status != TRUE)
  357.         return(status);
  358.  
  359.     return(buildlist(FALSE, mstring));
  360. }
  361.  
  362. buildlist(type, mstring)  /* build a binding list (limited or full) */
  363.  
  364. int type;    /* true = full list,   false = partial list */
  365. char *mstring;    /* match string if a partial list */
  366.  
  367. #endif
  368. {
  369. #if    ST520 & LATTICE
  370. #define    register        
  371. #endif
  372.     register WINDOW *wp;    /* scanning pointer to windows */
  373.     register KEYTAB *ktp;    /* pointer into the command table */
  374.     register NBIND *nptr;    /* pointer into the name binding table */
  375.     register BUFFER *bp;    /* buffer to put binding list into */
  376.     char *strp;        /* pointer int string to send */
  377.     int cpos;        /* current position to use in outseq */
  378.     char outseq[80];    /* output buffer for keystroke sequence */
  379.  
  380.     /* split the current window to make room for the binding list */
  381.     if (splitwind(FALSE, 1) == FALSE)
  382.             return(FALSE);
  383.  
  384.     /* and get a buffer for it */
  385.     bp = bfind("Binding list", TRUE, 0);
  386.     if (bp == NULL || bclear(bp) == FALSE) {
  387.         mlwrite("Can not display binding list");
  388.         return(FALSE);
  389.     }
  390.  
  391.     /* let us know this is in progress */
  392.     mlwrite("[Building binding list]");
  393.  
  394.     /* disconect the current buffer */
  395.         if (--curbp->b_nwnd == 0) {             /* Last use.            */
  396.                 curbp->b_dotp  = curwp->w_dotp;
  397.                 curbp->b_doto  = curwp->w_doto;
  398.                 curbp->b_markp = curwp->w_markp;
  399.                 curbp->b_marko = curwp->w_marko;
  400.         }
  401.  
  402.     /* connect the current window to this buffer */
  403.     curbp = bp;    /* make this buffer current in current window */
  404.     bp->b_mode = 0;        /* no modes active in binding list */
  405.     bp->b_nwnd++;        /* mark us as more in use */
  406.     wp = curwp;
  407.     wp->w_bufp = bp;
  408.     wp->w_linep = bp->b_linep;
  409.     wp->w_flag = WFHARD|WFFORCE;
  410.     wp->w_dotp = bp->b_dotp;
  411.     wp->w_doto = bp->b_doto;
  412.     wp->w_markp = NULL;
  413.     wp->w_marko = 0;
  414.  
  415.     /* build the contents of this window, inserting it line by line */
  416.     nptr = &names[0];
  417.     while (nptr->n_func != NULL) {
  418.  
  419.         /* add in the command name */
  420.         strcpy(outseq, nptr->n_name);
  421.         cpos = strlen(outseq);
  422.         
  423. #if    APROP
  424.         /* if we are executing an apropos command..... */
  425.         if (type == FALSE &&
  426.             /* and current string doesn't include the search string */
  427.             strinc(outseq, mstring) == FALSE)
  428.             goto fail;
  429. #endif
  430.         /* search down any keys bound to this */
  431.         ktp = &keytab[0];
  432.         while (ktp->k_fp != NULL) {
  433.             if (ktp->k_fp == nptr->n_func) {
  434.                 /* padd out some spaces */
  435.                 while (cpos < 25)
  436.                     outseq[cpos++] = ' ';
  437.  
  438.                 /* add in the command sequence */
  439.                 cmdstr(ktp->k_code, &outseq[cpos]);
  440.                 while (outseq[cpos] != 0)
  441.                     ++cpos;
  442.  
  443.                 /* and add it as a line into the buffer */
  444.                 strp = &outseq[0];
  445.                 while (*strp != 0)
  446.                     linsert(1, *strp++);
  447.                 lnewline();
  448.  
  449.                 cpos = 0;    /* and clear the line */
  450.             }
  451.             ++ktp;
  452.         }
  453.  
  454.         /* if no key was bound, we need to dump it anyway */
  455.         if (cpos > 0) {
  456.             outseq[cpos] = 0;
  457.             strp = &outseq[0];
  458.             while (*strp != 0)
  459.                 linsert(1, *strp++);
  460.             lnewline();
  461.         }
  462.  
  463. fail:        /* and on to the next name */
  464.         ++nptr;
  465.     }
  466.  
  467.     curwp->w_bufp->b_mode |= MDVIEW;/* put this buffer view mode */
  468.     curbp->b_flag &= ~BFCHG;    /* don't flag this as a change */
  469.     wp->w_dotp = lforw(bp->b_linep);/* back to the beginning */
  470.     wp->w_doto = 0;
  471.     wp = wheadp;            /* and update ALL mode lines */
  472.     while (wp != NULL) {
  473.         wp->w_flag |= WFMODE;
  474.         wp = wp->w_wndp;
  475.     }
  476.     mlwrite("");    /* clear the mode line */
  477.     return(TRUE);
  478. }
  479.  
  480. #if    APROP
  481. strinc(source, sub)    /* does source include sub? */
  482.  
  483. char *source;    /* string to search in */
  484. char *sub;    /* substring to look for */
  485.  
  486. {
  487.     char *sp;    /* ptr into source */
  488.     char *nxtsp;    /* next ptr into source */
  489.     char *tp;    /* ptr into substring */
  490.  
  491.     /* for each character in the source string */
  492.     sp = source;
  493.     while (*sp) {
  494.         tp = sub;
  495.         nxtsp = sp;
  496.  
  497.         /* is the substring here? */
  498.         while (*tp) {
  499.             if (*nxtsp++ != *tp)
  500.                 break;
  501.             else
  502.                 tp++;
  503.         }
  504.  
  505.         /* yes, return a success */
  506.         if (*tp == 0)
  507.             return(TRUE);
  508.  
  509.         /* no, onward */
  510.         sp++;
  511.     }
  512.     return(FALSE);
  513. }
  514. #endif
  515.  
  516. getckey(mflag)    /* get a command key sequence from the keyboard    */
  517.  
  518. int mflag;    /* going for a meta sequence? */
  519.  
  520. {
  521.     register int c;        /* character fetched */
  522.     register char *tp;    /* pointer into the token */
  523.     char tok[NSTRING];    /* command incoming */
  524.  
  525.     /* check to see if we are executing a command line */
  526.     if (clexec) {
  527.         macarg(tok);    /* get the next token */
  528.  
  529.         /* parse it up */
  530.         tp = &tok[0];
  531.         c = 0;
  532.  
  533.         /* first, the META prefix */
  534.         if (*tp == 'M' && *(tp+1) == '-') {
  535.             c = META;
  536.             tp += 2;
  537.         }
  538.  
  539.         /* next the function prefix */
  540.         if (*tp == 'F' && *(tp+1) == 'N') {
  541.             c |= SPEC;
  542.             tp += 2;
  543.         }
  544.  
  545.         /* control-x as well... */
  546.         if (*tp == '^' && *(tp+1) == 'X') {
  547.             c |= CTLX;
  548.             tp += 2;
  549.         }
  550.  
  551.         /* a control char? */
  552.         if (*tp == '^' && *(tp+1) != 0) {
  553.             c |= CTRL;
  554.             ++tp;
  555.         }
  556.  
  557.         /* make sure we are not lower case */
  558.         if (c >= 'a' && c <= 'z')
  559.             c -= 32;
  560.  
  561.         /* the final sequence... */
  562.         c |= *tp;
  563.  
  564.         return(c);
  565.     }
  566.  
  567.     /* or the normal way */
  568.     if (mflag)
  569.         c = get1key();
  570.     else
  571.         c = getcmd();
  572.     return(c);
  573. }
  574.  
  575. /* execute the startup file */
  576.  
  577. startup(sfname)
  578.  
  579. char *sfname;    /* name of startup file (null if default) */
  580.  
  581. {
  582.     char *fname;    /* resulting file name to execute */
  583.  
  584.     /* look up the startup file */
  585.     if (*sfname != 0)
  586.         fname = flook(sfname, TRUE);
  587.     else
  588.         fname = flook(pathname[0], TRUE);
  589.  
  590.     /* if it isn't around, don't sweat it */
  591.     if (fname == NULL)
  592.         return(TRUE);
  593.  
  594.     /* otherwise, execute the sucker */
  595.     return(dofile(fname));
  596. }
  597.  
  598. /*    Look up the existance of a file along the normal or PATH
  599.     environment variable. Look first in the HOME directory if
  600.     asked and possible
  601. */
  602.  
  603. char *flook(fname, hflag)
  604.  
  605. char *fname;    /* base file name to search for */
  606. int hflag;    /* Look in the HOME environment variable first? */
  607.  
  608. {
  609.     register char *home;    /* path to home directory */
  610.     register char *path;    /* environmental PATH variable */
  611.     register char *sp;    /* pointer into path spec */
  612.     register int i;        /* index */
  613.     register int status;    /* return status */
  614.     static char fspec[NSTRING];    /* full path spec to search */
  615.     char *getenv();
  616.  
  617. #if    ((MSDOS | AMIGA) & (LATTICE | AZTEC | MSC)) | V7 | USG | BSD
  618.  
  619.     if (hflag) {
  620.         home = getenv("HOME");
  621.         if (home != NULL) {
  622.             /* build home dir file spec */
  623.             strcpy(fspec, home);
  624.             strcat(fspec, "/");
  625.             strcat(fspec, fname);
  626.  
  627.             /* and try it out */
  628.             status = ffropen(fspec);
  629.             if (status == FIOSUC) {
  630.                 ffclose();
  631.                 return(fspec);
  632.             }
  633.         }
  634.     }
  635.  
  636.     /* get the PATH variable */
  637.     path = getenv("PATH");
  638.     if (path != NULL)
  639.         while (*path) {
  640.  
  641.             /* build next possible file spec */
  642.             sp = fspec;
  643.             while (*path && (*path != PATHCHR))
  644.                 *sp++ = *path++;
  645.             *sp++ = '/';
  646.             *sp = 0;
  647.             strcat(fspec, fname);
  648.  
  649.             /* and try it out */
  650.             status = ffropen(fspec);
  651.             if (status == FIOSUC) {
  652.                 ffclose();
  653.                 return(fspec);
  654.             }
  655.  
  656.             if (*path == PATHCHR)
  657.                 ++path;
  658.         }
  659. #endif
  660.  
  661.     /* look it up via the old table method */
  662.     for (i=2; i < NPNAMES; i++) {
  663.         strcpy(fspec, pathname[i]);
  664.         strcat(fspec, fname);
  665.  
  666.         /* and try it out */
  667.         status = ffropen(fspec);
  668.         if (status == FIOSUC) {
  669.             ffclose();
  670.             return(fspec);
  671.         }
  672.     }
  673.  
  674.     return(NULL);    /* no such luck */
  675. }
  676.  
  677.